﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;

using System.Text;
using System.Windows.Forms;
using ITAP.ShprossesBuilder.Render;
using ITAP.ShprossesBuilder.Info;
using ITAP.ShprossesBuilder.Modelling;
using ITAP.ShprossesBuilder.Calculations;
using ITAP.ShprossesBuilder.Modelling.Components;
using ITAP.ShprossesBuilder.Manipulation;
using System.Diagnostics;
using ITAP.ShprossesBuilder.Modelling.Components.Actions;
using ITAP.ShprossesBuilder.Operations;
using System.Reflection;
using System.IO;
using ITAP.ShprossesBuilder.Properties;
using System.Drawing.Imaging;
using System.Runtime.Serialization.Formatters.Binary;
using ITAP.ShprossesBuilder.Utils;
using ITAP.Core.Modelling.Primitives;
using ITAP.Core.Utils;

namespace ITAP.ShprossesBuilder.Editor
{
    public enum ShprossEditorType
    {
        Embedded,
        Standalone
    }

    public delegate void SaveShprossDelegate(ShprossMainForm shprossMainForm, ModelControl modelControl);

    public partial class ShprossMainForm : Form
    {
        private ShprossEditorType editorType;
        public event SaveShprossDelegate ShprossSaving;

        public static bool DebugMode
        {
            get
            {
                return GlobalPreferences.Debug;
            }
            set
            {
                GlobalPreferences.Debug = value;
            }
        }
        private List<IOperation> operations;
        private List<IOperation> customUserOperations;

        private CommandStackForm commandStackForm;
        private ITAP.ShprossesBuilder.Modelling.Components.IComponent draggedComponent;
        //        private ModelComponents modelComponents = null;

        public ShprossMainForm(ModelContainer modelContainer, ProfilesProviderDelegate profilesDelegate, ShprossEditorType editorType)
        {
            CreateModelContainerDelegate createModelContainerDelegate = new CreateModelContainerDelegate(delegate()
            {
                return modelContainer;
            });
            this.InitializeAll(createModelContainerDelegate, profilesDelegate, editorType);
        }

        private void InitializeAll(CreateModelContainerDelegate createModelContainerDelegate, ProfilesProviderDelegate profilesDelegate, ShprossEditorType editorType)
        {
            this.editorType = editorType;

            GlobalPreferences.LoadFromDefaultLocation();

            operations = new List<IOperation>();
            customUserOperations = new List<IOperation>();

            //  FakeProfileProvider fakeProvider = new FakeProfileProvider();

            InitializeComponent();
            commandStackForm = new CommandStackForm(mainControl.Manipulator, this);

            //this.mainControl.RegisterManipulatorVisitor(new VisitorInfo(treeViewModel, new Type[] { typeof(CommandEditorAddComponentToModel) }));
            //this.mainControl.RegisterManipulatorVisitor(new VisitorInfo(treeViewModel, new Type[] { typeof(CommandCreateModelContainer) }));
            //this.mainControl.RegisterManipulatorVisitor(new VisitorInfo(treeViewModel, new Type[] { typeof(CommandSelectComponent) }));
            this.mainControl.RegisterManipulatorVisitor(new VisitorInfo(customPropertyGridModel, new Type[] { typeof(CommandSelectComponent), typeof(CommandMoveComponent), typeof(CommandPropertyGridValueChanged), typeof(CommandEditorChangeShprossLength) }));
            this.mainControl.RegisterManipulatorVisitor(new VisitorInfo(commandStackForm,
                new Type[] { typeof(CommandMoveComponent), 
                             typeof(CommandPropertyGridValueChanged), 
                             typeof(CommandEditorAddComponentToModel), 
                             typeof(CommandOperation)}));

            this.customPropertyGridModel.PropertyValueChanged += new PropertyValueChangedEventHandler(customPropertyGridModel_PropertyValueChanged);


            this.customPropertyGridModel.AllowTypesToDisplay.Add(typeof(ModelContainer));
            this.customPropertyGridModel.AllowTypesToDisplay.Add(typeof(ModelCell));
            this.customPropertyGridModel.AllowTypesToDisplay.Add(typeof(ShprossConnector));
            this.customPropertyGridModel.AllowTypesToDisplay.Add(typeof(Shpross));
            this.customPropertyGridModel.AllowTypesToDisplay.Add(typeof(SnapOnCap));

            this.customPropertyGridModel.MainControl = this.mainControl;

            if (createModelContainerDelegate == null)
            {
                this.mainControl.Initialize(ModelProvider.CreateEmptyModel, profilesDelegate);
            }
            else
            {
                this.mainControl.Initialize(createModelContainerDelegate, profilesDelegate);
            }



            this.mainControl.ModelControl.Render = new Render.Render();

            this.mainControl.ModelControl.ModelContainer.FatalModelError += new FatalModelErrorDelegate(ModelContainer_FatalModelError);

            this.treeViewModel.MainControl = this.mainControl;

            this.materialPanel.Initialize(profilesDelegate, new ITAP.ShprossesBuilder.Render.ThumbnailRender(), new Size(GlobalPreferences.Preferences.ThumbnailSize, GlobalPreferences.Preferences.ThumbnailSize),
                              new Material[] { Material.SpacerConnector, Material.SnapOnCap, 
                                          Material.ShprossConnector, Material.Shpross }, this.mainControl, null);



            this.InitializeOperations();
            this.InitializeToolBar();
            this.InitializeMenu();
            this.ApplyMaterialsTabSettings();
            this.renderToolStripMenuItem.Visible = GlobalPreferences.Debug;
            this.mainControl.Manipulator.FatalModelError += new FatalModelErrorDelegate(Manipulator_FatalModelError);
        }



        void Manipulator_FatalModelError(IComponent sender, FatalErrorEventArgs e)
        {
            MessageBox.Show("При выполнении команды произошла ошибка");
            mainControl.Manipulator.History[mainControl.Manipulator.CurrentHistoryElementIndex].Undo(this.mainControl.ModelControl);
            mainControl.ModelContainer.FatalModelError += new FatalModelErrorDelegate(ModelContainer_FatalModelError);
        }

        public ShprossMainForm(CreateModelContainerDelegate createModelContainerDelegate, ProfilesProviderDelegate profilesDelegate, ShprossEditorType editorType)
        {
            this.InitializeAll(createModelContainerDelegate, profilesDelegate, editorType);
        }

        private void InitializeToolBar()
        {
            toolStripDropDownButtonDebug.Visible = GlobalPreferences.Debug;

            if (this.editorType == ShprossEditorType.Embedded)
            {
                toolStripButtonNew.Visible = false;
                toolStripButtonOpen.Visible = false;
            }
            toolStripButtonNew.Image = Resources.NewIcon;
            toolStripButtonSave.Image = Resources.SaveIcon;
            toolStripButtonOpen.Image = Resources.Open.ToBitmap();
            toolStripButtonUndo.Image = Resources.UndoIcon;
            toolStripButtonRedo.Image = Resources.RedoIcon;
            toolStripButtonHistory.Image = Resources.HistoryNew.ToBitmap();
            toolStripButtonLockModel.Image = Resources.locked;

            toolStripDropDownButtonMouseMoveType.Image = Resources.MouseMoveType.ToBitmap();
            mouseHorizontalToolStripMenuItem.Image = Resources.MouseMoveTypeHorizontal.ToBitmap();
            mouseVerticalToolStripMenuItem.Image = Resources.MouseMoveTypeVertical.ToBitmap();
            mouseBothDirectionsToolStripMenuItem.Image = Resources.MouseMoveTypeBoth.ToBitmap();

            List<ToolStripButton> shprossesOperationsButtons = new List<ToolStripButton>();
            List<ToolStripButton> shprossesConnectorsOperationsButtons = new List<ToolStripButton>();
            List<ToolStripButton> otherOperationsButtons = new List<ToolStripButton>();
            List<ToolStripButton> customOperationsButtons = new List<ToolStripButton>();

            List<IOperation> crossConnectorOperations = new List<IOperation>();
            
            foreach (IOperation operation in this.operations)
            {
                //if(operation is OperationCreateCrossConnectorsOnShprosses || operation is OperationBreakCrossConnection || operation is OperationRemoveCrossConnectorsFromShprosses) {
                //    crossConnectorOperations.Add(operation);
                //    continue;
                //}

                ToolStripButton button = this.CreateToolStripButton(operation);

                switch (operation.OperationGroup)
                {
                    case OperationGroup.ShprossOperation:
                        shprossesOperationsButtons.Add(button);
                        break;

                    case OperationGroup.ShprossConnectorOperation:
                        shprossesConnectorsOperationsButtons.Add(button);
                        break;

                    case OperationGroup.Other:
                        otherOperationsButtons.Add(button);
                        break;
                }
            }

           

            foreach (IOperation customOperation in this.customUserOperations)
            {
                customOperationsButtons.Add(this.CreateToolStripButton(customOperation));
            }

            ToolStripSeparator separator = new ToolStripSeparator();
            mainToolStrip.Items.Add(separator);
            foreach (ToolStripButton button in shprossesConnectorsOperationsButtons)
                mainToolStrip.Items.Add(button);

            separator = new ToolStripSeparator();
            mainToolStrip.Items.Add(separator);
            foreach (ToolStripButton button in shprossesOperationsButtons)
                mainToolStrip.Items.Add(button);

          //  ToolStripDropDownButton dropDownButton = this.CreateDropDownMenu("Пересечения профилей", crossConnectorOperations);
         //   mainToolStrip.Items.Add(dropDownButton);
            separator = new ToolStripSeparator();
            mainToolStrip.Items.Add(separator);
            foreach (ToolStripButton button in otherOperationsButtons)
                mainToolStrip.Items.Add(button);

            if (customUserOperations.Count != 0)
            {
                separator = new ToolStripSeparator();
                mainToolStrip.Items.Add(separator);
                foreach (ToolStripButton button in customUserOperations)
                    mainToolStrip.Items.Add(button);
            }
        }

        private ToolStripDropDownButton CreateDropDownMenu(string name, List<IOperation> operationList) {
            ToolStripDropDownButton menu = new ToolStripDropDownButton(name);
            menu.Text = name;
            EventHandler handler = new EventHandler(toolStripButton_Click);
            foreach(IOperation operation in operationList) {
                ToolStripMenuItem item = new ToolStripMenuItem(operation.Name, operation.Thumbnail, handler);
                item.Tag = operation;
                menu.DropDownItems.Add(item);
            }
            return menu;
        }

        private ToolStripButton CreateToolStripButton(IOperation operation)
        {
            EventHandler handler = new EventHandler(toolStripButton_Click);
            ToolStripButton button = new ToolStripButton(operation.Name, operation.Thumbnail, handler);
            button.DisplayStyle = ToolStripItemDisplayStyle.Image;
            button.ToolTipText = operation.Name;
            button.Tag = operation;
            return button;
        }

        private void toolStripButton_Click(object sender, EventArgs e)
        {
            ToolStripItem item = sender as ToolStripItem;

            //ToolStripButton button = sender as ToolStripButton;
            IOperation operation = item.Tag as IOperation;
            this.mainControl.Manipulator.ExecuteOperation(operation);
        }

        private void InitializeMenu()
        {
            if (this.editorType == ShprossEditorType.Embedded)
            {
                newToolStripMenuItem.Visible = false;
                openToolStripMenuItem.Visible = false;

            }

            newToolStripMenuItem.Image = Resources.NewIcon;
            openToolStripMenuItem.Image = Resources.Open.ToBitmap();
            saveToolStripMenuItem.Image = Resources.SaveIcon;
            saveAsToolStripMenuItem.Image = Resources.SaveIcon;
            undoToolStripMenuItem.Image = Resources.UndoIcon;
            redoToolStripMenuItem.Image = Resources.RedoIcon;
            historyToolStripMenuItem1.Image = Resources.HistoryNew.ToBitmap();
            toolStripButtonEnableDisableTolerance.Image = Resources.EnableDisableTolerance.ToBitmap();

            profilesToolStripMenuItem.DropDownItems.Clear();
            connectorsToolStripMenuItem.DropDownItems.Clear();
            otherToolStripMenuItem.DropDownItems.Clear();
            foreach (IOperation operation in operations)
            {
                ToolStripMenuItem operationsItem = new ToolStripMenuItem();
                operationsItem.Tag = operation;
                operationsItem.Text = operation.Name;
                operationsItem.Image = operation.Thumbnail;
                operationsItem.Click += new EventHandler(operationsItem_Click);

                switch (operation.OperationGroup)
                {
                    case OperationGroup.ShprossOperation:
                        profilesToolStripMenuItem.DropDownItems.Add(operationsItem);
                        break;
                    case OperationGroup.ShprossConnectorOperation:
                        connectorsToolStripMenuItem.DropDownItems.Add(operationsItem);
                        break;
                    case OperationGroup.Other:
                        otherToolStripMenuItem.DropDownItems.Add(operationsItem);
                        break;
                }
            }


            customOperationsToolStripMenuItem.DropDownItems.Clear();
            foreach (IOperation operation in customUserOperations)
            {
                ToolStripMenuItem operationsItem = new ToolStripMenuItem();
                operationsItem.Tag = operation;
                operationsItem.Text = operation.Name;
                operationsItem.Click += new EventHandler(operationsItem_Click);
                customOperationsToolStripMenuItem.DropDownItems.Add(operationsItem);
            }
            if (customUserOperations.Count == 0)
            {
                ToolStripMenuItem operationsItem = new ToolStripMenuItem();
                operationsItem.Text = "Пусто";
                operationsItem.Enabled = false;
                customOperationsToolStripMenuItem.DropDownItems.Add(operationsItem);
            }
        }

        private void InitializeOperations()
        {
            operations.Clear();
            //operations.Add(new OperationAlignSelectedComponentPositionsRelativeToModel(new Type[] { typeof(ShprossConnector) }));

            //operations.Add(new OperationAlignRelativeToModelHorizontal());
            //operations.Add(new OperationAlignRelativeToModelVertical());
            //operations.Add(new OperationAlignSelectedShprossConnectors());
            //operations.Add(new OperationAutoRotateShprossConnectors());
            //operations.Add(new OperationStickUnstickHalfSunConnectorToShpross());
            operations.Add(new OperationDisperseShprossConnectors());

            //operations.Add(new OperationAlignSelectedShprossConnectorsByDiamond());
            //operations.Add(new OperationCreateShprossDiamondByShprossConnector());

            operations.Add(new OperationCreateDiamondByConnectorPosition());
            //operations.Add(new OperationRotateShprossConnectors());
            //operations.Add(new OperationCreateShprossesOnShprossConnector());
            //operations.Add(new OperationFixSelectedShprossConnectorAngles());


            //operations.Add(new OperationAlignShprossesEndsRelativeToModelHorizontal());
            //operations.Add(new OperationAlignShprossesEndsRelativeToModelVertical());
            //operations.Add(new OperationAlignSelectedShprosses());
            //operations.Add(new OperationAlignSelectedShprossesByAngle());
            //operations.Add(new OperationAlignSelectedShprossesByAxes());
            //operations.Add(new OperationAlignSelectedShprossesPositions());
            //operations.Add(new OperationSetShprossesAnglesRelativeToAxes());
            //operations.Add(new OperationRotateComponent());
            //operations.Add(new OperationBreakSelectedShprossesToPieces());
            //operations.Add(new OperationSetDistanceBetweenShprossEnds());
            //operations.Add(new OperationJoinShprossesEnds());
            //operations.Add(new OperationCreateCrossConnectorsOnShprosses());
            //operations.Add(new OperationRemoveCrossConnectorsFromShprosses());
            //operations.Add(new OperationBreakCrossConnection());
            //operations.Add(new OperationComponentLayoutSendToBack());
            //operations.Add(new OperationComponentLayoutBringToFront());


            operations.Add(new OperationCreateShprossBetweenShprossConnectors());
            operations.Add(new OperationMoveComponentsWithOffset());
            operations.Add(new CommandMoveComponentsWithOffsetDiagonal());
            operations.Add(new OperationMoveWithOffsetRelativeToComponentPosition());
            operations.Add(new OperationOffsetFromModelBounds());
            operations.Add(new OperationAlignSelectedShprossesRelativeToComponentAndModel());
            operations.Add(new OperationShprossSnapsVisibleSwitcher());
            operations.Add(new OperationCreateShprossBarByShprossConnectors());
            operations.Add(new OperationCreateShprossBarByShprossesHorizontal());
            operations.Add(new OperationCreateShprossBarByShprossesVertical());
            operations.Add(new OperationCreateShprossBarByShprosses());

            if (GlobalPreferences.Debug)
            {
                operations.Add(new OperationShowAllModelComponents());
            }

            operations.Add(new OperationGetDistance());
            operations.Add(new OperationZoomIn());
            operations.Add(new OperationZoomOut());

            operations.Add(new OperationZoomAuto());
            operations.Add(new OperationZoomAutoForModel());
            //operations.Add(new OperationExportAsWmf());
            //operations.Add(new OperationPrint());
            operations.Add(new OperationRemoveComponent());
            operations.Add(new OperationClearSelectedModel());


            //   customUserOperations = CustomUserOperationsProvider.LoadOperationsFromFile("CustomOperations.dll");
        }

        void operationsItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem menuItem = ((ToolStripMenuItem)sender);
            this.mainControl.Manipulator.ExecuteOperation(((IOperation)menuItem.Tag));
        }


        void ModelContainer_FatalModelError(ITAP.ShprossesBuilder.Modelling.Components.IComponent sender, FatalErrorEventArgs e)
        {
            mainControl.Manipulator.History[mainControl.Manipulator.CurrentHistoryElementIndex].Undo(this.mainControl.ModelControl);
            mainControl.ModelContainer.FatalModelError += new FatalModelErrorDelegate(ModelContainer_FatalModelError);
        }

        void customPropertyGridModel_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            mainControl.ModelContainer.RecalculateCells();
            mainControl.ModelControl.ModelContainer.Update();
            mainControl.ModelControl.Invalidate();
            customPropertyGridModel.Refresh();
        }

        private void mainControl_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;

            object data = e.Data.GetData(typeof(ListViewItem));
            draggedComponent = (IComponent)((ITAP.ShprossesBuilder.Modelling.Components.IComponent)(((ListViewItem)data).Tag)).Clone();
        }

        private void mainControl_DragDrop(object sender, DragEventArgs e)
        {
            if (draggedComponent != null)
            {
                Point point = mainControl.PointToClient(new Point(e.X, e.Y));

                mainControl.MouseManager.MouseUp(point, new MouseManagerEvent(MouseButtons.None, mainControl.KeyData));

                IModelComponentCommand addComponentCommand = new CommandEditorAddComponentToModel(mainControl.ModelControl, new Type[] { typeof(ShprossEndToEndConnector), typeof(CrossConnector), typeof(StickConnector), typeof(Shpross), typeof(SpacerConnector), typeof(ShprossConnector), typeof(Model) }, "");
                addComponentCommand.ComponentsForProcessing.Add(draggedComponent);
                addComponentCommand.MouseUpPoint = point;
                mainControl.Manipulator.StartExecute(addComponentCommand);
                mainControl.Manipulator.Execute(addComponentCommand);
                mainControl.Manipulator.EndExecute(addComponentCommand);
                e.Effect = DragDropEffects.None;
            }

        }

        private void toolStripButtonRedo_Click(object sender, EventArgs e)
        {
            mainControl.Manipulator.Redo();
        }

        private void toolStripButtonUndo_Click(object sender, EventArgs e)
        {
            mainControl.Manipulator.Undo();
        }

        private void ShprossMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.mainControl.ModelContainer.InnerComponents.Count == 0)
                return;

            DialogResult dialogResult = MessageBox.Show("Сохранить раскладку?", "Выход из редактора раскладки", MessageBoxButtons.YesNoCancel);
            if (dialogResult == DialogResult.Yes)
            {
                this.Save();
            }
            else if (dialogResult == DialogResult.Cancel)
                e.Cancel = true;
        }

        private void treeViewModel_AfterSelect(object sender, TreeViewEventArgs e)
        {

        }

        private void treeViewModel_AfterCheck(object sender, TreeViewEventArgs e)
        {
            this.mainControl.ModelControl.Invalidate();
        }

        private void стекКомандToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            commandStackForm.Show();
        }

        private void стандартныйToolStripMenuItem_Click(object sender, EventArgs e)
        {
            standardRenderToolStripMenuItem.Checked = true;
            debugRenderToolStripMenuItem1.Checked = false;
            this.mainControl.ModelControl.Render = new Render.Render();
            this.mainControl.ModelControl.Invalidate();

        }

        private void debugRenderToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            standardRenderToolStripMenuItem.Checked = false;
            debugRenderToolStripMenuItem1.Checked = true;
            this.mainControl.ModelControl.Render = new SimpleRender();
            this.mainControl.ModelControl.Invalidate();
        }

        private void showDimensionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            showDimensionsToolStripMenuItem.Checked = !showDimensionsToolStripMenuItem.Checked;
            this.mainControl.ModelControl.Render.EnableDimensions = showDimensionsToolStripMenuItem.Checked;
            this.mainControl.ModelControl.UpdateModel();
        }

        private void modelDimensionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            modelDimensionsToolStripMenuItem.Checked = !modelDimensionsToolStripMenuItem.Checked;
            this.mainControl.ModelControl.Render.DimensionProcessor.SetCompute(modelDimensionsToolStripMenuItem.Checked, typeof(Model));
            this.mainControl.ModelControl.UpdateModel();

        }

        private void profileDimensionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            profileDimensionsToolStripMenuItem.Checked = !profileDimensionsToolStripMenuItem.Checked;
            this.mainControl.ModelControl.Render.DimensionProcessor.SetCompute(profileDimensionsToolStripMenuItem.Checked, typeof(Shpross));

            this.mainControl.ModelControl.UpdateModel();
        }

        private void pinHolesDimensionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            pinHolesDimensionsToolStripMenuItem.Checked = !pinHolesDimensionsToolStripMenuItem.Checked;
            this.mainControl.ModelControl.Render.DimensionProcessor.SetCompute(pinHolesDimensionsToolStripMenuItem.Checked, typeof(Spacer));
            this.mainControl.ModelControl.UpdateModel();
        }

        private void spacerElementsDimensionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            spacerElementsDimensionsToolStripMenuItem.Checked = !spacerElementsDimensionsToolStripMenuItem.Checked;
            this.mainControl.ModelControl.Render.DimensionProcessor.SetCompute(spacerElementsDimensionsToolStripMenuItem.Checked, typeof(SpacerElement));
            this.mainControl.ModelControl.UpdateModel();
        }

        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.mainControl.Manipulator.CurrentHistoryElementIndex != 0)
                this.mainControl.Manipulator.Undo();
        }

        private void redoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.mainControl.Manipulator.CurrentHistoryElementIndex != this.mainControl.Manipulator.History.Count - 1)
                this.mainControl.Manipulator.Redo();
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PreferencesForm preferences = new PreferencesForm();
            if (preferences.ShowDialog() == DialogResult.OK)
            {
                GlobalPreferences.SaveToDefaultLocation();
                this.materialPanel.SetThumbnailSize(new Size(GlobalPreferences.Preferences.ThumbnailSize, GlobalPreferences.Preferences.ThumbnailSize));
                this.ApplyMaterialsTabSettings();
                this.mainControl.ModelControl.UpdateModel();
            }
        }

        private void toolStripButtonUndo_Click_1(object sender, EventArgs e)
        {
            this.mainControl.Manipulator.Undo();
        }

        private void toolStripButtonRedo_Click_1(object sender, EventArgs e)
        {
            this.mainControl.Manipulator.Redo();
        }

        private void toolStripButtonHistory_Click(object sender, EventArgs e)
        {
            commandStackForm.Show();
        }

        private void toolStripButtonNew_Click(object sender, EventArgs e)
        {
            IOperation newOperation = new OperationNew();
            this.mainControl.Manipulator.ExecuteOperation(newOperation);
        }

        private void toolStripButtonSave_Click(object sender, EventArgs e)
        {
            this.Save();
        }

        private void toolStripButtonOpen_Click(object sender, EventArgs e)
        {
            IOperation openOperation = new OperationBinaryOpen();
            this.mainControl.Manipulator.ExecuteOperation(openOperation);
            this.mainControl.ModelContainer.FatalModelError += new FatalModelErrorDelegate(this.ModelContainer_FatalModelError);
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IOperation newOperation = new OperationNew();
            this.mainControl.Manipulator.ExecuteOperation(newOperation);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IOperation openOperation = new OperationBinaryOpen();
            this.mainControl.Manipulator.ExecuteOperation(openOperation);
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Save();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutForm about = new AboutForm();
            about.ShowDialog();
        }

        private void mainControl_GiveFeedback(object sender, GiveFeedbackEventArgs e)
        {

        }



        public Metafile[] GetModelsWmf()
        {
            OperationGetModelsWmf getWmfOperation = new OperationGetModelsWmf();
            getWmfOperation.Execute(this.mainControl.ModelControl);
            return getWmfOperation.Metafiles.ToArray();
        }

        public byte[] GetModeCelllZippedByteArrray(int modelId)
        {
            OperationSaveModelCellToZippedByteArray saveToByteArray = new OperationSaveModelCellToZippedByteArray(modelId);
            saveToByteArray.Execute(this.mainControl.ModelControl);
            return saveToByteArray.ZippedModelBytes;
        }

        //public void LoadZippedModel(byte[] modelBytes) {
        //    OperationLoadZippedModel loadModel = new OperationLoadZippedModel(modelBytes);
        //    loadModel.Execute(this.mainControl.ModelControl);
        //}

        public static ModelCell UnzipModelCell(byte[] zippedBytes)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            stream.Write(zippedBytes, 0, zippedBytes.Length);
            MemoryStream unzippedStream = new MemoryStream();
            stream.Seek(0, SeekOrigin.Begin);
            Archiver.UnZip(stream, unzippedStream);
            object _modelCell = formatter.Deserialize(unzippedStream);
            ModelCell modelCell = _modelCell as ModelCell;
            stream.Close();
            unzippedStream.Close();
            return modelCell;

        }

        public byte[] GetModelMetafile(int modelId)
        {
            OperationGetModelWmf getModelWmf = new OperationGetModelWmf(modelId);
            getModelWmf.Execute(this.mainControl.ModelControl);
            return getModelWmf.WmfBytes;
        }

        private void mouseHorizontalToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            mouseBothDirectionsToolStripMenuItem.Checked = false;
            mouseVerticalToolStripMenuItem.Checked = false;
            mouseHorizontalToolStripMenuItem.Checked = true;

            this.mainControl.MouseManager.MoveDirection = MoveDirection.Horizontal;

        }

        private void mouseVerticalToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            mouseBothDirectionsToolStripMenuItem.Checked = false;
            mouseVerticalToolStripMenuItem.Checked = true;
            mouseHorizontalToolStripMenuItem.Checked = false;

            this.mainControl.MouseManager.MoveDirection = MoveDirection.Vertical;
        }

        private void mouseBothDirectionsToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            mouseBothDirectionsToolStripMenuItem.Checked = true;
            mouseVerticalToolStripMenuItem.Checked = false;
            mouseHorizontalToolStripMenuItem.Checked = false;
            this.mainControl.MouseManager.MoveDirection = MoveDirection.Both;
        }

        private void toolStripButtonHand_Click(object sender, EventArgs e)
        {
            toolStripButtonHand.Checked = true;
            toolStripButtonSelect.Checked = false;
        }

        private void toolStripButtonSelect_Click(object sender, EventArgs e)
        {
            toolStripButtonHand.Checked = false;
            toolStripButtonSelect.Checked = true;

        }

        private void toolStripButtonLockModel_Click(object sender, EventArgs e)
        {
            toolStripButtonLockModel.Checked = !toolStripButtonLockModel.Checked;
            this.mainControl.MouseManager.EnableDisableCommand(typeof(CommandMoveComponent), !toolStripButtonLockModel.Checked);
        }

        private void UpdateMoveDirection(MoveDirection direction)
        {
            if (direction == MoveDirection.Vertical)
            {
                mouseVerticalToolStripMenuItem.Checked = true;
                mouseHorizontalToolStripMenuItem.Checked = false;
                mouseBothDirectionsToolStripMenuItem.Checked = false;
            }
            else if (direction == MoveDirection.Horizontal)
            {
                mouseHorizontalToolStripMenuItem.Checked = true;
                mouseBothDirectionsToolStripMenuItem.Checked = false;
                mouseVerticalToolStripMenuItem.Checked = false;
            }
            else
            {
                mouseBothDirectionsToolStripMenuItem.Checked = true;
                mouseHorizontalToolStripMenuItem.Checked = false;
                mouseVerticalToolStripMenuItem.Checked = false;
            }
        }

        private void mainControl_KeyDown(object sender, KeyEventArgs e)
        {
            //   this.UpdateMoveDirection();
        }

        private void mainControl_MouseMove(object sender, MouseEventArgs e)
        {
            this.UpdateMoveDirection(this.mainControl.GetMoveDirection());

        }

        private void toolStripButtonEnableDisableTolerance_Click(object sender, EventArgs e)
        {
            toolStripButtonEnableDisableTolerance.Checked = !toolStripButtonEnableDisableTolerance.Checked;
            this.mainControl.ToleranceManager.Enabled = toolStripButtonEnableDisableTolerance.Checked;
            this.mainControl.ToleranceManager.Update();
            this.mainControl.ModelControl.UpdateModel();
        }

        private void ApplyMaterialsTabSettings()
        {
            this.RecreateTabControl(GlobalPreferences.Preferences.MaterialsTabOrientation);
        }

        private void RecreateTabControl(Orientation orientation)
        {
            this.splitContainerMailControl.Panel1.Controls.Clear();
            this.splitContainerMailControl.Panel2.Controls.Clear();

            if (orientation == Orientation.Vertical)
            {
                int materialPanelHeight = materialPanel.Height;
                this.splitContainerMailControl.Panel2.Controls.Add(this.mainControl);
                this.splitContainerMailControl.Panel1.Controls.Add(this.materialPanel);
                this.splitContainerMailControl.Orientation = Orientation.Vertical;
                this.splitContainerMailControl.FixedPanel = FixedPanel.Panel1;
                this.splitContainerMailControl.SplitterDistance = materialPanelHeight;
            }
            else
            {
                this.splitContainerMailControl.Panel2.Controls.Add(this.materialPanel);
                this.splitContainerMailControl.Panel1.Controls.Add(this.mainControl);
                if (this.splitContainerMailControl.Orientation == Orientation.Vertical)
                {
                    int materialPanelWidth = this.splitContainerMailControl.Panel1.Width;
                    this.splitContainerMailControl.Orientation = Orientation.Horizontal;
                    this.splitContainerMailControl.FixedPanel = FixedPanel.Panel2;
                    this.splitContainerMailControl.SplitterDistance = this.splitContainerMailControl.Height - materialPanelWidth;
                }
                else if (this.splitContainerMailControl.Orientation == Orientation.Horizontal)
                {
                    int materialPanelHeight = materialPanel.Height;
                    this.splitContainerMailControl.SplitterDistance = this.splitContainerMailControl.Height - materialPanelHeight;

                }
            }
            this.materialPanel.Orientation = orientation;
        }

        private void materialPanel_Resize(object sender, EventArgs e)
        {
            //if (materialPanel.Orientation == Orientation.Horizontal)
            //    GlobalPreferences.Preferences.MaterialsPanelHeight = materialPanel.Height;
            //else if (materialPanel.Orientation == Orientation.Vertical)
            //    GlobalPreferences.Preferences.MaterialsPanelHeight = materialPanel.Width;
            //GlobalPreferences.SaveToDefaultLocation();
        }

        private void splitContainerMailControl_SplitterMoved(object sender, SplitterEventArgs e)
        {

        }

        private void materialPanel_Load(object sender, EventArgs e)
        {

        }

        public new DialogResult ShowDialog()
        {
            DialogResult result = DialogResult.None;
            if (!GlobalPreferences.Debug)
            {
                try
                {
                    result = base.ShowDialog();
                }
                catch (Exception ex)
                {
                    ExceptionHelper helper = new ExceptionHelper("1.0");
                    helper.ExceptionLog(ex, this.mainControl.ModelControl);
                }
            }
            else
            {
                result = base.ShowDialog();
            }
            return result;
        }



        private void выходToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
            //DialogResult dialogResult = MessageBox.Show("Сохранить раскладку?", "Выход из редактора раскладки", MessageBoxButtons.YesNoCancel);
            //if (dialogResult == DialogResult.OK)
            //{
            //    this.Save();
            //    this.Close();
            //}
            //else if (dialogResult == DialogResult.No)
            //    this.Close();
            //else if (dialogResult == DialogResult.Cancel)
            //    return;
        }

        private void Save()
        {
            if (this.editorType == ShprossEditorType.Standalone)
            {
                IOperation saveOperation = new OperationBinarySave();
                this.mainControl.Manipulator.ExecuteOperation(saveOperation);
            }
            else if (this.editorType == ShprossEditorType.Embedded)
            {
                if (this.ShprossSaving != null)
                    this.ShprossSaving.Invoke(this, this.mainControl.ModelControl);
            }
        }

        private void zipUnzipModelCellToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<byte[]> modelCellsBytes = new List<byte[]>();
            modelCellsBytes.Add(this.GetModeCelllZippedByteArrray(0));

            ModelCell cell = ShprossMainForm.UnzipModelCell(modelCellsBytes[0]);
            modelCellsBytes.Add(this.GetModeCelllZippedByteArrray(1));
            ModelCell cell1 = ShprossMainForm.UnzipModelCell(modelCellsBytes[0]);
            ModelCell cell2 = ShprossMainForm.UnzipModelCell(modelCellsBytes[1]);

            this.mainControl.ModelContainer = new ModelContainer();
            ModelCellRepository repository = new ModelCellRepository();
            repository.AddCell(cell2, 0, 0);
            //repository.AddCell(cell1, 0, 1);
            this.mainControl.ModelContainer.Initialize(repository);

        }

        private void getPinHolesDistancesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (IComponent component in this.mainControl.ModelContainer.AllInnerComponents)
            {
                if (component is SpacerElement)
                {
                    SpacerElement element = component as SpacerElement;
                    List<IEndedPrimitive> primitives = Utils.PinHolesDistanceHelper.GetSpacerElementPinHolesDistances(element, ITAP.ShprossesBuilder.Modelling.Measurement.DimensionType.InnerDimension);
                }                                                                                                     
            }
        }



        private void toolStripMenuItemWmfExport_Click(object sender, EventArgs e) {
            IOperation saveWmf = new OperationExportAsWmf();
            this.mainControl.Manipulator.ExecuteOperation(saveWmf);

        }

        private void toolStripMenuItemPrint_Click(object sender, EventArgs e) {
            IOperation print = new OperationPrint();
            this.mainControl.Manipulator.ExecuteOperation(print);

        }

        private void mainControl_Load(object sender, EventArgs e)
        {

        }

        private void getModelsWmfBytesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OperationGetModelWmf getBytesOperation = new OperationGetModelWmf(1);
            this.mainControl.Manipulator.ExecuteOperation(getBytesOperation);
        }


        public byte[] GetModelMetafileBytes(int modelId)
        {
            OperationGetModelWmf getBytesOperation = new OperationGetModelWmf(modelId);
            this.mainControl.Manipulator.ExecuteOperation(getBytesOperation);
            return getBytesOperation.WmfBytes;
        }

    }
}
